package com.mzpai.util.generate;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.mzpai.util.DateUtil;
import com.mzpai.util.StringUtils;

public abstract class GenerateBase<T> {
  private final String FILE_URL_PREFIX = "file:/";
  private final String TARGET_CLASSES = "target/classes";
  private final String SRC_MAIN_JAVA = "src/main/java";
  protected final String PO = "model";
  protected final String POJO = "vo";
  protected final String POINT = ".";
  protected final String EMPTY = "";
  protected final String SPACES = " ";
  protected final String SEMICOLON = ";";
  protected final String NEXT_LINE = "\n";
  protected final String JAVA_SUFFIX = ".java";
  protected Class<T> clazz;
  protected String CLAZZ_NAME;
  protected String CLAZZ_SIMPLE_NAME;
  protected String PATH;
  protected String SUFFIX;
  protected String PACKAGE;
  protected String SUPERCLASS;
  protected String PACKAGE_TYPE;
  protected String IMPL;
  protected String CTX;
  protected String MODULE_NAME;
  protected String AUTHOR;
  protected List<String> IMPORT_LIST = new ArrayList<String>();
  protected List<String> CLASS_LINE_LIST = new ArrayList<String>();
  protected boolean impl = false;

  @SuppressWarnings("static-access")
public GenerateBase(Class<T> clazz, String packageType, String moduleName, String author) {
	  
	  if("service.impl".equals(packageType)) {
		  impl = true;
	  }
	  
    this.clazz = clazz;
    this.PACKAGE_TYPE = packageType;
    this.MODULE_NAME = moduleName;
    this.AUTHOR = author;
    this.CLAZZ_NAME = clazz.getName();
    this.CLAZZ_SIMPLE_NAME = clazz.getSimpleName();
    if (PACKAGE_TYPE.indexOf(POINT) > 0) {
      IMPL = PACKAGE_TYPE.substring(PACKAGE_TYPE.indexOf(POINT) + 1);
      PACKAGE_TYPE = PACKAGE_TYPE.substring(0, PACKAGE_TYPE.indexOf(POINT));
    }
    if (StringUtils.isNotEmpty(IMPL)) {
      this.SUFFIX = this.firstToUpperCase(PACKAGE_TYPE) + this.firstToUpperCase(IMPL);
    } else {
      this.SUFFIX = this.firstToUpperCase(PACKAGE_TYPE);
    }
    getPath();
    getCtx();
    generaePackage();
    generaeImport();
    generaeCalss();
    fileWriter();
  }

  private void getPath() {
    PATH = clazz.getResource(EMPTY).toString();
    PATH = replace(PATH, FILE_URL_PREFIX, EMPTY);
    PATH = replace(PATH, TARGET_CLASSES, SRC_MAIN_JAVA);
    /**path = info*/
    if (StringUtils.isNotEmpty(IMPL)) {
      PATH = replacePoOrPojoSeparator(PATH, PACKAGE_TYPE) + IMPL + "/";
    } else {
      PATH = replacePoOrPojoSeparator(PATH, PACKAGE_TYPE);
    }
    
    if("mapper".equals(PACKAGE_TYPE)) {
    	PATH = PATH.replace("", "");
    } else if("service".equals(PACKAGE_TYPE) && !impl) {
    	PATH = PATH.replace("", "");
    } else if("service".equals(PACKAGE_TYPE) && impl) {
    	PATH = PATH.replace("", "");
    } else if("controller".equals(PACKAGE_TYPE)) {
    	PATH = PATH.replace("mzpai-product-service", "mzpai-product-web").replace("/product", "/web");
    }
    
  }

  private void getCtx() {
    CTX = replace(CLAZZ_NAME, "com.sohu.crm.", EMPTY);
    CTX = CTX.substring(0, CTX.indexOf(POINT));
  }

  private void generaePackage() {
    PACKAGE = clazz.getPackage().toString();
    if (StringUtils.isNotEmpty(IMPL)) {
      PACKAGE = replacePoOrPojoPoint(PACKAGE, PACKAGE_TYPE) + POINT + IMPL;
    } else {
      PACKAGE = replacePoOrPojoPoint(PACKAGE, PACKAGE_TYPE);
    }
    PACKAGE = PACKAGE + SEMICOLON + NEXT_LINE;
    
    if("mapper".equals(PACKAGE_TYPE)) {
    	PACKAGE = PACKAGE.replace("", "");
    } else if("service".equals(PACKAGE_TYPE) && !impl) {
    	PACKAGE = PACKAGE.replace("", "");
    } else if("service".equals(PACKAGE_TYPE) && impl) {
    	PACKAGE = PACKAGE.replace("", "");
    } else if("controller".equals(PACKAGE_TYPE)) {
    	PACKAGE = PACKAGE.replace("product", "web");
    }
  }

  private void generaeCalss() {
    generaeNote();
    generaeCalssTitle();
    generaeCalssContext();
    addClassLine("}");
  }

  protected void addImport(String packageName, boolean addSuffix) {
    StringBuffer sb = new StringBuffer("import ");
    sb.append(packageName);
    if (addSuffix) {
      sb.append(SUFFIX);
    }
    sb.append(SEMICOLON);
    sb.append(NEXT_LINE);
    if (IMPORT_LIST.contains(sb.toString()) == false) {
      IMPORT_LIST.add(sb.toString());
    }
  }

  protected void addClassLine(String classLine) {
    CLASS_LINE_LIST.add(classLine);
  }

  private void fileWriter() {
    File file = new File(PATH);
    if (file.exists() == false) {
      file.mkdirs();
    }
    String CLASS_FILE = PATH + CLAZZ_SIMPLE_NAME + SUFFIX + JAVA_SUFFIX;
    boolean is = new File(CLASS_FILE).delete();
    if(is) {}
    FileWriter fileWriter = null;
    try {
      System.out.println(CLASS_FILE);
      fileWriter = new FileWriter(CLASS_FILE, true);
      System.out.println(PACKAGE);
      fileWriter.write(PACKAGE);
      for (String importStr : IMPORT_LIST) {
        System.out.println(importStr);
        fileWriter.write(importStr);
      }
      for (String classLine : CLASS_LINE_LIST) {
        System.out.println(classLine);
        fileWriter.write(classLine);
      }
      fileWriter.flush();
    } catch (Exception e) {
    } finally {
    	try {
    		if(fileWriter != null) {
    			fileWriter.close();
    		}
		} catch (IOException e) {
		}
    }
  }

  @SuppressWarnings("static-access")
protected void generaeNote() {
    StringBuffer sb = new StringBuffer("/**");
    sb.append(NEXT_LINE);
    sb.append(" *");
    sb.append(NEXT_LINE);
    sb.append(" * <b>");
    sb.append(MODULE_NAME);
    sb.append(" | ");
    sb.append(this.firstToUpperCase(PACKAGE_TYPE));
    sb.append("</b><br>");
    sb.append(NEXT_LINE);
    sb.append(" *");
    sb.append(NEXT_LINE);
    sb.append(" * ");
    sb.append(AUTHOR);
    sb.append(" ");
    sb.append(DateUtil.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
    sb.append(NEXT_LINE);
    sb.append(" * ");
    sb.append(NEXT_LINE);
    sb.append(" *  @version 1.0.0");
    sb.append(NEXT_LINE);
    sb.append(" *");
    sb.append(NEXT_LINE);
    sb.append(" */");
    sb.append(NEXT_LINE);
    addClassLine(sb.toString());
  }

  protected abstract void generaeImport();

  protected abstract void generaeCalssTitle();

  protected abstract void generaeCalssContext();

  public String replace(String source, String oldStr, String newStr) {
    if (source == null || source.length() == 0) {
      return source;
    }
    return source.replace(oldStr, newStr);
  }

  protected String addPoint(String str) {
    return POINT + str;
  }

  protected String addSeparator(String str) {
    return "/" + str + "/";
  }

  protected String replacePoOrPojoSeparator(String source, String target) {
    if (source == null || source.length() == 0) {
      return source;
    }
    source = replace(source, addSeparator(PO), addSeparator(target));
    return replace(source, addSeparator(POJO), addSeparator(target));
  }

  protected String replacePoOrPojoPoint(String source, String target) {
    if (source == null || source.length() == 0) {
      return source;
    }
    source = replace(source, addPoint(PO), addPoint(target));
    return replace(source, addPoint(POJO), addPoint(target));
  }
  
  /**
  * 首字母大写
  * 
  * @param str
  * @return String
  * @since 1.0.0
  */
 public static String firstToUpperCase(String str) {
   if (str != null && str.length() != 0) {
     return Character.toUpperCase(str.charAt(0)) + str.substring(1);
   }
   return str;
 }
  
}
